﻿namespace Hainet

[<Measure>]
type Pixel

[<Measure>]
type Rad

[<Measure>]
type Step

[<Measure>]
type Pps = Pixel / Step

type Boundary = Top | Bottom | Left | Right

(*type Dir =
    | Right = 0.0<Rad>
    | Up = 1.5707963267948966192313216916398<Rad>
    | Left = 3.1415926535897932384626433832795<Rad>
    | Right = 4.7123889803846898576939650749193<Rad>*)

//[<Measure>]
//type Deg = Rad / 57.295779513082320876798154814105

type Vector< [<Measure>] 'a>(x: float<'a>, y: float<'a>) =
    member this.X = x
    member this.Y = y
    member this.Direction =
        if x = 0.0<_> then
            0.0<Rad>
        else
            atan2 (float y) (float x) * 1.0<Rad>
    
    member this.Length = sqrt <| x * x + y * y
        //and set (spd: float<'a>) = let dir = float this.Direction
        //                           this.X <- spd * cos dir
        //                           this.Y <- -spd * sin dir
    static member (+) (a: Vector<'a>, b: Vector<'a>) =
        new Vector<'a>(x = a.X + b.X, y = a.Y + b.Y)
    
    static member (*) (p: float<'b>, vec: Vector<'a>) =
        new Vector<'a * 'b>(x = p * vec.X, y = p * vec.Y)    
    new () = new Vector<'a>(0.0<_>, 0.0<_>)
    
type Point< [<Measure>] 'a>(x: float<'a>, y: float<'a>) =
    member this.X = x
    member this.Y = y
    new () = new Point<'a>(0.0<_>, 0.0<_>)

    
type Size = Point<Pixel>
type Position = Vector<Pixel>
type Speed = Vector<Pps>
type Acceleration = Vector<Pps / Step>

